package cn.schoolwow.workflow.module.task.action.flow.complete.nodeType.gateway;

import cn.schoolwow.quickdao.domain.transaction.Transaction;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.query.instanceList.QueryInstanceList;
import cn.schoolwow.workflow.domain.deploy.DeployGatewayPositionType;
import cn.schoolwow.workflow.domain.task.TaskType;
import cn.schoolwow.workflow.entity.WorkFlowInstance;
import cn.schoolwow.workflow.entity.WorkFlowNode;
import cn.schoolwow.workflow.entity.WorkFlowNodeJump;
import cn.schoolwow.workflow.module.common.flow.AddWorkFlowHistoryFlow;
import cn.schoolwow.workflow.module.task.action.domain.CompleteTaskOption;
import cn.schoolwow.workflow.module.task.action.flow.complete.nodeType.gateway.common.CompleteGatewayEndNodeCommonFlow;
import cn.schoolwow.workflow.module.task.action.flow.complete.nodeType.gateway.common.SetCurrentGatewayNodeCommonFlow;
import cn.schoolwow.workflow.module.task.action.flow.complete.nodeType.gateway.common.SetMatchSuccessorJumpNodeListCommonFlow;
import cn.schoolwow.workflow.module.task.action.flow.complete.transaction.InsertWorkFlowTaskFlow;

import java.util.List;

public class HandleInclusiveGatewayFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        flowContext.executeFlowList(new SetCurrentGatewayNodeCommonFlow());
        checkExclusiveGatewayStart(flowContext);
        checkExclusiveGatewayEnd(flowContext);
    }

    @Override
    public String name() {
        return "处理包容网关流程";
    }

    private void checkExclusiveGatewayStart(FlowContext flowContext){
        WorkFlowNode gatewayNode = flowContext.checkData("gatewayNode", WorkFlowNode.class);
        DeployGatewayPositionType deployGatewayPositionType = flowContext.checkInstanceData(DeployGatewayPositionType.class);

        if(!DeployGatewayPositionType.Start.equals(deployGatewayPositionType)){
            return;
        }

        WorkFlowInstance workFlowInstance = flowContext.checkInstanceData(WorkFlowInstance.class);
        CompleteTaskOption completeTaskOption = flowContext.checkInstanceData(CompleteTaskOption.class);
        Transaction transaction = flowContext.checkInstanceData(Transaction.class);

        flowContext.executeFlowList(new SetMatchSuccessorJumpNodeListCommonFlow());

        List<WorkFlowNodeJump> matchWorkFlowNodeJumpList = flowContext.getData("matchWorkFlowNodeJumpList", List.class);

        List<Long> nextNodeIdList = QueryInstanceList.newQuery(matchWorkFlowNodeJumpList)
                .execute()
                .getSingleFieldValueList("nextNodeId");
        List<WorkFlowNode> workFlowNodeList = transaction.query(WorkFlowNode.class)
                .addInQuery("id",nextNodeIdList)
                .execute()
                .getList();

        for(WorkFlowNodeJump workFlowNodeJump:matchWorkFlowNodeJumpList){
            WorkFlowNode nextNode = QueryInstanceList.newQuery(workFlowNodeList)
                    .addQuery("id", workFlowNodeJump.getNextNodeId())
                    .execute()
                    .getOne();
            if(null==nextNode){
                throw new IllegalArgumentException("工作流节点id为["+workFlowNodeJump.getNextNodeId()+"]的节点不存在!实例名称:"+workFlowInstance.getName());
            }

            flowContext.startFlow(new AddWorkFlowHistoryFlow())
                    .putCurrentCompositeFlowData("message", "选择分支["+workFlowNodeJump.getJumpName()+"]")
                    .execute();

            flowContext.startFlow(new InsertWorkFlowTaskFlow())
                    .putCurrentCompositeFlowData("nextNode", nextNode)
                    .putCurrentCompositeFlowInstanceData(TaskType.COMPLETE)
                    .execute();
        }

        completeTaskOption.shouldUpdateInstanceCurrentNodeId = true;
        workFlowInstance.setWorkFlowNodeId(gatewayNode.getId());
    }

    private void checkExclusiveGatewayEnd(FlowContext flowContext){
        DeployGatewayPositionType deployGatewayPositionType = flowContext.checkInstanceData(DeployGatewayPositionType.class);

        if(!DeployGatewayPositionType.End.equals(deployGatewayPositionType)){
            return;
        }

        flowContext.executeFlowList(new CompleteGatewayEndNodeCommonFlow());
    }
}
